package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogItemParser;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Pattern;

@Slf4j
public class LogItemParserLhImpl implements LogItemParser {

    private static final Pattern LOG_PATTERN = Pattern.compile("(?<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+[\\w\\-]+\\s+[\\w\\-]+\\s+\\[(?<dt>\\d+/\\w+/\\d+:\\d+:\\d+:\\d+\\s+\\+\\d+)]\\s+\"(?<request>.*)\"\\s+(?<status>\\d+)\\s+(?<sent>\\d+)\\s+\"(?<referer>[^\"]+)\"\\s+\"(?<ua>[^\"]+)\"");
    private static final Pattern REQUEST_PATTERN = Pattern.compile("(?<method>\\w+)\\s+(?<url>[^ ]+)\\s+(?<protocol>[^ ]+)");

    @Override

    public Optional<LogItem> parse(String line) {
        if (line == null) {
            return Optional.empty();
        }
        val m = LOG_PATTERN.matcher(line);
        if (!m.matches()) {
            log.error("Error parsing line: {}", line);
            return Optional.empty();
        }
        String path = null;
        String protocol = null;
        String method = null;
        val request = REQUEST_PATTERN.matcher(m.group("request"));
        if (request.matches()) {
            method = request.group("method");
            path = request.group("url");
            protocol = request.group("protocol");
        }
//TODO 调整时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH);
        LocalDateTime localtime = LocalDateTime.parse(m.group("dt"), formatter);
        return Optional.of(new LogItem(
                m.group("ip"),
                localtime,
                m.group("request"),
                method,
                path,
                new HashMap<>(),
                protocol,
                Integer.parseInt(m.group("status"))
                , Long.parseLong(m.group("sent")),
                m.group("referer"),
                m.group("ua")
        ));

    }

}
